"""
命令行接口主程序
"""
import argparse
import sys
import os
from datetime import datetime
from monitor import ProcessMonitor, ProcessNotFoundError
from database import Database
from visualizer import MemoryVisualizer


def monitor_process(process_name=None, process_id=None, interval=1.0, 
                   duration=None, save_db=True, plot_realtime=False,
                   output_dir="output"):
    """
    监控进程内存
    
    Args:
        process_name: 进程名称
        process_id: 进程ID
        interval: 监控间隔（秒）
        duration: 监控持续时间（秒）
        save_db: 是否保存到数据库
        plot_realtime: 是否实时绘制图表
        output_dir: 输出目录
    """
    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 初始化组件
    db = Database(os.path.join(output_dir, "memory_monitor.db"))
    visualizer = MemoryVisualizer()
    
    try:
        monitor = ProcessMonitor(process_name=process_name, process_id=process_id)
    except ProcessNotFoundError as e:
        print(f"错误: {e}", file=sys.stderr)
        sys.exit(1)
    
    print(f"开始监控进程: {process_name or f'PID {process_id}'}")
    print(f"监控间隔: {interval} 秒")
    if duration:
        print(f"监控时长: {duration} 秒")
    else:
        print("监控将持续到进程结束或手动停止（Ctrl+C）")
    print("-" * 50)
    
    records = []
    
    def on_record(timestamp, pid, pname, memory_mb, memory_percent):
        """记录回调函数"""
        records.append((timestamp, pid, pname, memory_mb, memory_percent))
        
        # 保存到数据库
        if save_db:
            db.insert_record(pname, pid, memory_mb, memory_percent)
        
        # 打印当前状态
        print(f"[{timestamp}] PID: {pid}, 内存: {memory_mb:.2f} MB ({memory_percent:.2f}%)")
    
    try:
        # 开始监控
        monitor.monitor(interval=interval, duration=duration, callback=on_record)
    except KeyboardInterrupt:
        print("\n监控已停止")
    
    # 绘制最终图表
    if records:
        timestamp_str = datetime.now().strftime("%Y%m%d_%H%M%S")
        process_identifier = process_name or f"pid_{process_id}"
        output_path = os.path.join(output_dir, f"memory_chart_{process_identifier}_{timestamp_str}.png")
        
        title = f"进程内存监控 - {process_name or f'PID {process_id}'}"
        visualizer.plot_from_records(records, output_path=output_path, 
                                    title=title, show_plot=True)
        
        # 显示统计信息
        stats = db.get_statistics(process_id=process_id)
        print("\n" + "=" * 50)
        print("统计信息:")
        print(f"  记录数量: {stats['record_count']}")
        print(f"  最大内存: {stats['max_memory_mb']:.2f} MB")
        print(f"  最小内存: {stats['min_memory_mb']:.2f} MB")
        print(f"  平均内存: {stats['avg_memory_mb']:.2f} MB")
        print("=" * 50)
    else:
        print("没有收集到数据")


def plot_from_database(process_id=None, start_time=None, end_time=None,
                      output_dir="output", show_plot=True):
    """
    从数据库读取数据并绘制图表
    
    Args:
        process_id: 进程ID
        start_time: 开始时间
        end_time: 结束时间
        output_dir: 输出目录
        show_plot: 是否显示图表
    """
    db_path = os.path.join(output_dir, "memory_monitor.db")
    
    if not os.path.exists(db_path):
        print(f"错误: 数据库文件不存在: {db_path}", file=sys.stderr)
        print("\n提示:", file=sys.stderr)
        print("  数据库文件不存在，请先运行监控以生成数据。", file=sys.stderr)
        print("  示例命令:", file=sys.stderr)
        if process_id:
            print(f"    python cli.py --pid {process_id} --interval 1 --duration 60", file=sys.stderr)
        else:
            print("    python cli.py --pid <进程ID> --interval 1 --duration 60", file=sys.stderr)
        print("  或者:", file=sys.stderr)
        print("    python cli.py --name <进程名> --interval 1 --duration 60", file=sys.stderr)
        sys.exit(1)
    
    db = Database(db_path)
    
    # 检查数据库中是否有数据
    records = db.get_records(process_id=process_id, 
                            start_time=start_time, 
                            end_time=end_time)
    
    if not records:
        print("错误: 数据库中没有找到匹配的数据", file=sys.stderr)
        if process_id:
            print(f"  指定的进程ID: {process_id}", file=sys.stderr)
        if start_time:
            print(f"  开始时间: {start_time}", file=sys.stderr)
        if end_time:
            print(f"  结束时间: {end_time}", file=sys.stderr)
        print("\n提示:", file=sys.stderr)
        print("  请检查:", file=sys.stderr)
        print("    1. 进程ID是否正确", file=sys.stderr)
        print("    2. 时间范围是否包含监控数据", file=sys.stderr)
        print("    3. 是否已运行过监控并保存了数据", file=sys.stderr)
        sys.exit(1)
    
    visualizer = MemoryVisualizer()
    
    timestamp_str = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_path = os.path.join(output_dir, f"memory_chart_{timestamp_str}.png")
    
    title = f"进程内存监控历史数据"
    if process_id:
        title += f" - PID {process_id}"
    
    visualizer.plot_from_database(db, process_id=process_id,
                                 start_time=start_time,
                                 end_time=end_time,
                                 output_path=output_path,
                                 title=title,
                                 show_plot=show_plot)


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="内存监控工具 - 监控指定进程的内存占用并绘制时间-内存曲线图",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  # 通过进程名监控
  python cli.py --name chrome --interval 2 --duration 60
  
  # 通过进程ID监控
  python cli.py --pid 1234 --interval 1
  
  # 从数据库绘制历史图表
  python cli.py --plot --pid 1234
        """
    )
    
    # 模式选择
    parser.add_argument('--plot', action='store_true',
                       help='从数据库绘制历史图表（不监控）')
    
    # 进程选择参数（互斥，仅在非--plot模式下必需）
    process_group = parser.add_mutually_exclusive_group(required=False)
    process_group.add_argument('--name', '-n', type=str, 
                              help='进程名称（支持部分匹配）')
    process_group.add_argument('--pid', '-p', type=int,
                              help='进程ID（监控模式或绘图模式筛选）')
    
    # 监控参数
    parser.add_argument('--interval', '-i', type=float, default=1.0,
                       help='监控间隔（秒），默认: 1.0')
    parser.add_argument('--duration', '-d', type=float,
                       help='监控持续时间（秒），默认: 持续监控直到进程结束')
    parser.add_argument('--no-db', action='store_true',
                       help='不保存数据到数据库')
    parser.add_argument('--output-dir', '-o', type=str, default='output',
                       help='输出目录，默认: output')
    
    # 绘图参数（用于--plot模式）
    parser.add_argument('--start-time', type=str,
                       help='开始时间（ISO格式，如: 2024-01-01T10:00:00）')
    parser.add_argument('--end-time', type=str,
                       help='结束时间（ISO格式，如: 2024-01-01T12:00:00）')
    parser.add_argument('--no-show', action='store_true',
                       help='不显示图表（仅保存文件）')
    
    args = parser.parse_args()
    
    # 参数验证：非--plot模式下必须指定进程
    if not args.plot and not args.name and not args.pid:
        parser.error("监控模式需要指定 --name 或 --pid")
    
    # 处理绘图模式
    if args.plot:
        plot_from_database(process_id=args.pid,
                          start_time=args.start_time,
                          end_time=args.end_time,
                          output_dir=args.output_dir,
                          show_plot=not args.no_show)
    else:
        # 监控模式
        monitor_process(process_name=args.name,
                       process_id=args.pid,
                       interval=args.interval,
                       duration=args.duration,
                       save_db=not args.no_db,
                       output_dir=args.output_dir)


if __name__ == "__main__":
    main()

